home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65 / src / domain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-05  |  6.9 KB  |  280 lines

  1. /*
  2.  * Copyright (c) 1986 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted provided
  7.  * that: (1) source distributions retain this entire copyright notice and
  8.  * comment, and (2) distributions including binaries display the following
  9.  * acknowledgement:  ``This product includes software developed by the
  10.  * University of California, Berkeley and its contributors'' in the
  11.  * documentation or other materials provided with the distribution and in
  12.  * all advertising materials mentioning features or use of this software.
  13.  * Neither the name of the University nor the names of its contributors may
  14.  * be used to endorse or promote products derived from this software without
  15.  * specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #include "sendmail.h"
  22.  
  23. #ifndef lint
  24. #ifdef NAMED_BIND
  25. static char sccsid[] = "@(#)domain.c    5.22 (Berkeley) 6/1/90 (with name server)";
  26. #else
  27. static char sccsid[] = "@(#)domain.c    5.22 (Berkeley) 6/1/90 (without name server)";
  28. #endif
  29. #endif /* not lint */
  30.  
  31. #ifdef NAMED_BIND
  32.  
  33. #include <sys/param.h>
  34. #include <errno.h>
  35. #include <arpa/nameser.h>
  36. #include <resolv.h>
  37. #include <netdb.h>
  38.  
  39. typedef union {
  40.     HEADER qb1;
  41.     char qb2[PACKETSZ];
  42. } querybuf;
  43.  
  44. static char hostbuf[MAXMXHOSTS*PACKETSZ];
  45.  
  46. getmxrr(host, mxhosts, localhost, rcode)
  47.     char *host, **mxhosts, *localhost;
  48.     int *rcode;
  49. {
  50.     extern int h_errno;
  51.     register u_char *eom, *cp;
  52.     register int i, j, n, nmx;
  53.     register char *bp;
  54.     HEADER *hp;
  55.     querybuf answer;
  56.     int ancount, qdcount, buflen, seenlocal;
  57.     u_short pref, localpref, type, prefer[MAXMXHOSTS];
  58.  
  59.     errno = 0;
  60.     n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer));
  61.     if (n < 0)
  62.     {
  63.         if (tTd(8, 1))
  64.             printf("getmxrr: res_search failed (errno=%d, h_errno=%d)\n",
  65.                 errno, h_errno);
  66.         switch (h_errno)
  67.         {
  68.           case NO_DATA:
  69.           case NO_RECOVERY:
  70.             /* no MX data on this host */
  71.             goto punt;
  72.  
  73.           case HOST_NOT_FOUND:
  74.             /* the host just doesn't exist */
  75.             *rcode = EX_NOHOST;
  76.             break;
  77.  
  78.           case TRY_AGAIN:
  79.             /* couldn't connect to the name server */
  80.             if (!UseNameServer && errno == ECONNREFUSED)
  81.                 goto punt;
  82.  
  83.             /* it might come up later; better queue it up */
  84.             *rcode = EX_TEMPFAIL;
  85.             break;
  86.         }
  87.  
  88.         /* irreconcilable differences */
  89.         return (-1);
  90.     }
  91.  
  92.     /* find first satisfactory answer */
  93.     hp = (HEADER *)&answer;
  94.     cp = (u_char *)&answer + sizeof(HEADER);
  95.     eom = (u_char *)&answer + n;
  96.     for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
  97.         if ((n = dn_skipname(cp, eom)) < 0)
  98.             goto punt;
  99.     nmx = 0;
  100.     seenlocal = 0;
  101.     buflen = sizeof(hostbuf);
  102.     bp = hostbuf;
  103.     ancount = ntohs(hp->ancount);
  104.     while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS) {
  105.         if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
  106.             break;
  107.         cp += n;
  108.         GETSHORT(type, cp);
  109.          cp += sizeof(u_short) + sizeof(u_long);
  110.         GETSHORT(n, cp);
  111.         if (type != T_MX)  {
  112.             if (tTd(8, 1) || _res.options & RES_DEBUG)
  113.                 printf("unexpected answer type %d, size %d\n",
  114.                     type, n);
  115.             cp += n;
  116.             continue;
  117.         }
  118.         GETSHORT(pref, cp);
  119.         if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
  120.             break;
  121.         cp += n;
  122.         if (!strcasecmp(bp, localhost)) {
  123.             if (seenlocal == 0 || pref < localpref)
  124.                 localpref = pref;
  125.             seenlocal = 1;
  126.             continue;
  127.         }
  128.         prefer[nmx] = pref;
  129.         mxhosts[nmx++] = bp;
  130.         n = strlen(bp) + 1;
  131.         bp += n;
  132.         buflen -= n;
  133.     }
  134.     if (nmx == 0) {
  135. punt:        mxhosts[0] = strcpy(hostbuf, host);
  136.         return(1);
  137.     }
  138.  
  139.     /* sort the records */
  140.     for (i = 0; i < nmx; i++) {
  141.         for (j = i + 1; j < nmx; j++) {
  142.             if (prefer[i] > prefer[j] ||
  143.                 (prefer[i] == prefer[j] && rand() % 1 == 0)) {
  144.                 register int temp;
  145.                 register char *temp1;
  146.  
  147.                 temp = prefer[i];
  148.                 prefer[i] = prefer[j];
  149.                 prefer[j] = temp;
  150.                 temp1 = mxhosts[i];
  151.                 mxhosts[i] = mxhosts[j];
  152.                 mxhosts[j] = temp1;
  153.             }
  154.         }
  155.         if (seenlocal && prefer[i] >= localpref) {
  156.             /*
  157.              * truncate higher pref part of list; if we're
  158.              * the best choice left, we should have realized
  159.              * awhile ago that this was a local delivery.
  160.              */
  161.             if (i == 0) {
  162.                 *rcode = EX_CONFIG;
  163.                 return(-1);
  164.             }
  165.             nmx = i;
  166.             break;
  167.         }
  168.     }
  169.     return(nmx);
  170. }
  171.  
  172. getcanonname(host, hbsize)
  173.     char *host;
  174.     int hbsize;
  175. {
  176.     extern int h_errno;
  177.     register u_char *eom, *cp;
  178.     register int n; 
  179.     HEADER *hp;
  180.     querybuf answer;
  181.     u_short type;
  182.     int first, ancount, qdcount, loopcnt;
  183.     char nbuf[PACKETSZ];
  184.  
  185.     loopcnt = 0;
  186. loop:
  187.     /*
  188.      * Use query type of ANY if possible (NO_WILDCARD_MX), which will
  189.      * find types CNAME, A, and MX, and will cause all existing records
  190.      * to be cached by our local server.  If there is (might be) a
  191.      * wildcard MX record in the local domain or its parents that are
  192.      * searched, we can't use ANY; it would cause fully-qualified names
  193.      * to match as names in a local domain.
  194.      */
  195. # ifdef NO_WILDCARD_MX
  196.     n = res_search(host, C_IN, T_ANY, (char *)&answer, sizeof(answer));
  197. # else
  198.     n = res_search(host, C_IN, T_CNAME, (char *)&answer, sizeof(answer));
  199. # endif
  200.     if (n < 0) {
  201.         if (tTd(8, 1))
  202.             printf("getcanonname:  res_search failed (errno=%d, h_errno=%d)\n",
  203.                 errno, h_errno);
  204.         return;
  205.     }
  206.  
  207.     /* find first satisfactory answer */
  208.     hp = (HEADER *)&answer;
  209.     ancount = ntohs(hp->ancount);
  210.  
  211.     /* we don't care about errors here, only if we got an answer */
  212.     if (ancount == 0) {
  213.         if (tTd(8, 1))
  214.             printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
  215.         return;
  216.     }
  217.     cp = (u_char *)&answer + sizeof(HEADER);
  218.     eom = (u_char *)&answer + n;
  219.     for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
  220.         if ((n = dn_skipname(cp, eom)) < 0)
  221.             return;
  222.  
  223.     /*
  224.      * just in case someone puts a CNAME record after another record,
  225.      * check all records for CNAME; otherwise, just take the first
  226.      * name found.
  227.      */
  228.     for (first = 1; --ancount >= 0 && cp < eom; cp += n) {
  229.         if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
  230.             sizeof(nbuf))) < 0)
  231.             break;
  232.         if (first) {            /* XXX */
  233.             (void)strncpy(host, nbuf, hbsize);
  234.             host[hbsize - 1] = '\0';
  235.             first = 0;
  236.         }
  237.         cp += n;
  238.         GETSHORT(type, cp);
  239.          cp += sizeof(u_short) + sizeof(u_long);
  240.         GETSHORT(n, cp);
  241.         if (type == T_CNAME)  {
  242.             /*
  243.              * assume that only one cname will be found.  More
  244.              * than one is undefined.  Copy so that if dn_expand
  245.              * fails, `host' is still okay.
  246.              */
  247.             if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
  248.                 sizeof(nbuf))) < 0)
  249.                 break;
  250.             (void)strncpy(host, nbuf, hbsize); /* XXX */
  251.             host[hbsize - 1] = '\0';
  252.             if (++loopcnt > 8)    /* never be more than 1 */
  253.                 return;
  254.             goto loop;
  255.         }
  256.     }
  257. }
  258.  
  259. #else /* not NAMED_BIND */
  260.  
  261. #include <netdb.h>
  262.  
  263. getcanonname(host, hbsize)
  264.     char *host;
  265.     int hbsize;
  266. {
  267.     struct hostent *hp;
  268.  
  269.     hp = gethostbyname(host);
  270.     if (hp == NULL)
  271.         return;
  272.  
  273.     if (strlen(hp->h_name) >= hbsize)
  274.         return;
  275.  
  276.     (void) strcpy(host, hp->h_name);
  277. }
  278.  
  279. #endif /* not NAMED_BIND */
  280.